package com.zjcloud.jwgl.service.impl;

import com.zjcloud.jwgl.domain.ScheduleResult;
import com.zjcloud.jwgl.domain.ScheduleGene;
import com.zjcloud.jwgl.service.IScheduleService;
import com.zjcloud.jwgl.algorithm.GeneticAlgorithmUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Comparator;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ScheduleServiceImpl implements IScheduleService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public ScheduleResult generateSchedule(List<Long> courseIds) {
        // 初始化种群
        List<ScheduleGene> population = GeneticAlgorithmUtil.initPopulation(courseIds);
        
        // 迭代优化
        for(int i=0; i<1000; i++) {
            // 计算适应度（包含12种约束条件）
            population = population.stream()
                .<ScheduleGene>map(gene -> {
                    // 调用计算适应度方法并返回更新后的基因
                    return GeneticAlgorithmUtil.calculateFitness(gene, redisTemplate);
                })
                .sorted(Comparator.comparingDouble(ScheduleGene::getFitness).reversed())
                .limit(100)
                .collect(Collectors.toList());
            
            // 遗传操作
            population = GeneticAlgorithmUtil.evolve(population);
        }
        
        ScheduleResult result = new ScheduleResult(population.get(0));
        redisTemplate.opsForValue().set("schedule:" + result.getId(), result, 1, TimeUnit.HOURS);
        return result;
    }

    @Override
    public void manualAdjust(String scheduleId, int sourceSlot, int targetSlot) {
        ScheduleResult schedule = (ScheduleResult) redisTemplate.opsForValue().get("schedule:" + scheduleId);
        if (schedule != null) {
            schedule.moveCourse(sourceSlot, targetSlot);
            redisTemplate.opsForValue().set("schedule:" + scheduleId, schedule, 1, TimeUnit.HOURS);
            if (!checkConflict(scheduleId)) {
                redisTemplate.opsForValue().set("schedule:" + scheduleId, schedule);
            }
        }
    }

    @Override
    public boolean checkConflict(String scheduleId) {
        // 从Redis获取最新排课数据实现毫秒级响应
        ScheduleResult schedule = (ScheduleResult) redisTemplate.opsForValue().get("schedule:" + scheduleId);
        return schedule != null && schedule.hasConflicts();
    }
}